package org.yn.dept.service.impl;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yn.base.constants.BaseConstants;
import org.yn.base.service.impl.BaseServiceImpl;
import org.yn.base.util.BaiduAuditUtil;
import org.yn.base.util.LoginContext;
import org.yn.base.util.MD5Utils;
import org.yn.base.util.SendMailUtil;
import org.yn.dept.domain.Shop;
import org.yn.dept.domain.ShopEmployee;
import org.yn.dept.domain.ShopOperateLog;
import org.yn.dept.dto.ShopAdminDTO;
import org.yn.dept.dto.ShopExamineDTO;
import org.yn.dept.dto.ShopRegisterDTO;
import org.yn.dept.mapper.ShopEmployeeMapper;
import org.yn.dept.mapper.ShopMapper;
import org.yn.dept.mapper.ShopOperateLogMapper;
import org.yn.dept.service.IShopService;
import org.yn.emp.domain.Employee;
import org.yn.emp.mapper.EmployeeMapper;
import org.yn.exception.AssertUtil;
import org.yn.exception.BusinessException;
import org.yn.exception.ResponseCode;
import org.yn.user.domain.Logininfo;
import org.yn.user.mapper.LogininfoMapper;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author yn
 * @since 2023-08-15
 */
@Service
public class ShopServiceImpl extends BaseServiceImpl<Shop> implements IShopService {

    @Autowired
    ShopMapper shopMapper;

    @Autowired
    SendMailUtil sendMailUtil;

    @Autowired
    EmployeeMapper employeeMapper;
    @Autowired
    RedisTemplate redisTemplate;
    @Value("${MD5.preFix}")
    String preFix;
    @Value("${MD5.endFix}")
    String endFix;
    @Autowired
    private ShopEmployeeMapper shopEmployeeMapper;
    @Autowired
    private ShopOperateLogMapper logMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;

    @Transactional
    @Override
    public void settlement(ShopRegisterDTO dto) {
        ShopAdminDTO admin = dto.getAdmin(); //获取 dto里面的admin
        // 1 参数校验
        validate(dto, admin);  // 封装成了方法
        Shop shop = new Shop();
        ShopOperateLog log = new ShopOperateLog();

        // 对店铺    文本审核+图片审核

        List<String> text = Arrays.asList(dto.getName(),dto.getAddress());
        List<String> img = Arrays.asList(dto.getLogo());
        Map<String,Object> map = BaiduAuditUtil.censor(text,img); //单个单个的处理太麻烦 合并到一起处理

        // 获取处理后的 success是true还是false
        Boolean censorResult = (Boolean) map.get("success");
        if(censorResult){ //true为 没有违规信息
            shop.setState(BaseConstants.Shop.STATE_WAIT_ACTIVE); // 将店铺的状态改为 "审核通过，待激活";
            log.setOperateType(2);  // 操作日志里面修改 type为2   2=审核成功
            log.setNote("机器人审核通过!");
        }else{//有违规信息
            shop.setState(BaseConstants.Shop.STATE_REJECT_AUDIT);  //状态为驳回
            log.setOperateType(3);    //日志也写驳回
            log.setNote(map.get("message").toString());//将违规的信息写进去
        }

        //  保存店铺信息到数据库表
        BeanUtils.copyProperties(dto,shop);
        shop.setRegisterTime(new Date());
        if (shop.getId()==null||shop.getId().equals("")){ //id为空 为新增
            shopMapper.insert(shop);
        }else {
            shopMapper.update(shop); //跟新
        }

        // 新增logininfo
        Logininfo logininfo = new Logininfo();
        logininfo.setUsername(admin.getUsername());
        logininfo.setPhone(admin.getPhone());
        logininfo.setEmail(admin.getEmail());

        //密码处理
        //盐值
        String salt = UUID.randomUUID().toString();
        logininfo.setSalt(salt);   //保存
        //加密
        String password = MD5Utils.encrypByMd5(preFix + salt + admin.getPassword() + endFix);
        logininfo.setPassword(password);//保存加密后的密码

        logininfo.setType(0);
        logininfo.setDisable(1);
        logininfoMapper.insert(logininfo);




        // 保存店铺管理员信息到数据库

        //  新增的店铺就用已经存在的管理员作为店铺的管理员 新增店铺和已存在的管理员进行绑定
        //先判断管理员是否存在  根据手机号判断是否是同一个人
        Employee employee = employeeMapper.getByPhone(admin.getPhone());

        if(Objects.isNull(employee)){
            // 如果不存在,新增管理员信息,并将新增的管理员id和店铺id做绑定
            //判断用户的用户名和邮箱是否重复   求出来的可能是个List 就用list接收 必尽可能存在 单个用户名和邮箱重复
            List<Employee> employeeList = employeeMapper.getByUserNameOrEmail(admin.getUsername(),admin.getEmail());
            if(employeeList.size()!=0){
                throw new RuntimeException("管理员的用户名或邮箱已存在,请重新输入");

            }
            // 新增管理员
            employee = new Employee();
            BeanUtils.copyProperties(logininfo,employee);
            employee.setId(null); //不能用logininfo的id
            // 管理员要等店铺审核通过激活以后,才能正常登录使用
            employee.setState(BaseConstants.Employee.STATE_WAIT_AUTID);
            employee.setLogininfoId(logininfo.getId());
            employeeMapper.insert(employee);
        }


        // 将新增的管理员和店铺做绑定   修改中间表
        ShopEmployee shopEmployee = new ShopEmployee();
        shopEmployee.setShopId(shop.getId());
        shopEmployee.setEmployeeId(employee.getId());
        shopEmployee.setIsAdmin(1);
        shopEmployeeMapper.insert(shopEmployee);

        // 保存操作日志
        log.setShopId(shop.getId());
        log.setOperateTime(new Date());
//        log.setOperateId(0L);       // 自动审核 可以不写也可以写0
        logMapper.insert(log);

        sendEmail(admin.getEmail(), shop, map, censorResult);
    }

    //    激活
    @Override
    public void activationById(Long id) {
        // 高级激活
        // 生成一个uuid 一起返回给前端(在发送邮件的时候做）， 并且给redis赋值，定时30分钟 ，超时删除
        // 前端点击激活的时候，将UUID一起传回后端，后端 先判断UUID过时没有，过时就直接返回前端说过时了
        // 没有过时则给账号激活

        //UUID
//        String uuidValue = UUID.randomUUID().toString();

        //获取redis中的值,
        String key=BaseConstants.ACTIVATION_IN_REDIS+id;
//        redisTemplate.opsForValue().get(key);
        Boolean aBoolean = redisTemplate.hasKey(key);

        // 如果不存在 说明过期 返回给前端说此连接已经过期，请重新激活

        if (aBoolean!=true){// 不存在了
            throw new BusinessException("此连接已经过期，请重新激活!!!");
        }

        Shop shop = shopMapper.selectById(id);
        shop.setState(3);


        ShopOperateLog log = new ShopOperateLog();
        log.setOperateTime(new Date());
        log.setOperateType(3);
        log.setShopId(id);
        log.setNote("店铺激活成功");

        //激活成功后修改管理员状态
        Employee employee = employeeMapper.selectById(shop.getAdmin().getId());
        employee.setState(1);
        employeeMapper.update(employee);
        shopMapper.update(shop);
        logMapper.insert(log);

        redisTemplate.delete(key);// 激活成功后删除
    }

    // 没有审核通过，通过邮箱链接重新审核 而查询之前的数据避免重复填写
    @Override
    public Shop getShopRegister(Long id) {
        Shop shop = shopMapper.selectById(id);
        return shop;
    }

//    审核操作
    @Override
    public void examine(ShopExamineDTO dto) {
        //获取到 id 状态 ，文本
        // 根据id获取到对应的对象
        Shop shop = shopMapper.selectById(dto.getId());
        // 修改其状态
        shop.setState(dto.getState());

        // 修改操作日志  如果为驳回则添加
        ShopOperateLog log = new ShopOperateLog();
        log.setShopId(shop.getId());
        log.setOperateTime(new Date());
        String note="手动审核: ";
        if (dto.getState()==2){
            note+="审核通过，待激活！";
        }else if(dto.getState()==4) {
            note+="审核驳回：驳回原因："+dto.getTextarea();
        }
        log.setNote(note);
        log.setOperateType(dto.getState());
        Employee loginAdmin = LoginContext.getLoginAdmin();
        log.setOperateId(loginAdmin.getId());// 操作的管理员写进去

        shopMapper.update(shop);
        logMapper.insert(log);


        // 发送驳回邮件
        if (dto.getState()==4){
            HashMap<String, Object> map = new HashMap<>();
            map.put("message",dto.getTextarea());
            // 发送失败邮件
            sendEmail(shop.getAdmin().getEmail(),shop,map,false);
        }

        // 如果审核通过 发送激活邮件 ,
        if (dto.getState()==2){
            HashMap<String, Object> map = new HashMap<>();
            map.put("message","");
            // 发送成功邮件
            sendEmail(shop.getAdmin().getEmail(),shop,map,true);
        }

    }

    // 发送邮件
    private void sendEmail(String adminEmail, Shop shop, Map<String, Object> map, Boolean censorResult) {
        //  审核成功,修改店铺状态=待激活,发送激活邮件给店铺管理员,进行激活
        if(censorResult){ // true为 没有违规信息
            // 发送激活邮件给店铺管理员
            System.out.println("----"+ adminEmail);

            // 高级激活
            String uuidValue = UUID.randomUUID().toString();
            String key=BaseConstants.ACTIVATION_IN_REDIS+ shop.getId();

            redisTemplate.opsForValue().set(key,uuidValue,60*10, TimeUnit.SECONDS);//传入值并设置过期时间

//            String Content =new String("审核通过，<a href='http://localhost:8080/shop/activation/"+shop.getId()+"'>点击此处完成激活</a>");
            String Content2 ="审核通过，请激活：，<a href='http://localhost:8081/#/activation?id="+ shop.getId()+"'>点击此处完成激活</a>";  // 跳转到前端
            sendMailUtil.sendHtmlMail("522503535@qq.com", adminEmail,"激活店铺",Content2);


        }else{//有违规信息
            //  发送失败通知邮件给店铺管理员
           String message= map.get("message").toString();
            String Content ="店铺审核失败，原因："+message+"，<a href='http://localhost:8081/#/shopRegister?id="+ shop.getId()+"'>点击此处重新完成激活</a>";
            sendMailUtil.sendHtmlMail("522503535@qq.com", adminEmail,"审核失败",Content);
        }
    }

    private void validate(ShopRegisterDTO dto, ShopAdminDTO admin) {
        // 非空校验
//        if(     dto == null || admin == null
//                || StringUtils.isBlank(dto.getName()) || StringUtils.isBlank(dto.getTel())
//                || StringUtils.isBlank(dto.getAddress()) || StringUtils.isBlank(admin.getUsername())
//                || StringUtils.isBlank(admin.getPhone())  || StringUtils.isBlank(admin.getEmail())
//                || StringUtils.isBlank(admin.getPassword())  || StringUtils.isBlank(admin.getConfirmPassword())){
//            throw new RuntimeException("参数异常,请重新检查是否有遗漏");
//        }
//
//        // 判断两次密码是否一致
//        if(!admin.getPassword().equals(admin.getConfirmPassword())){
//            throw new RuntimeException("输入密码不一致,请检查");
//        }

        //用断言工具类
        AssertUtil.isEq(admin.getPassword(),admin.getConfirmPassword(), ResponseCode.RESPONSE_CODE_40011);
        //  校验店铺名称是否重复
        // 根据店铺名称查询店铺表
        Shop shop = shopMapper.getByName(dto.getName());


//        if(Objects.nonNull(shop)){//      存在店铺  抛出异常
//            throw new RuntimeException("该店铺名称已存在,请重新输入!");
//        }
        //替换上面的
        AssertUtil.isNull(shop,ResponseCode.RESPONSE_CODE_40012);

    }


}
